#ifndef RELAY_APP_H
#define RELAY_APP_H

#include <string>
#include <cstdio>
#include <ctime>
#include <sys/time.h>

#include "PCF8574.h"
#include "esp_task_manager.h"
#include "config/settings.h"
/**
 * @brief 继电器控制应用
 * 完全兼容继电器通讯协议，支持8字节协议格式
 * 协议格式：[0x55, 地址, 功能码, 数据1, 数据2, 数据3, 数据4, 校验和]
 * 支持14路双线圈继电器控制 (1-10为双引脚，11-14为单引脚)
 */
class RelayApp {
public:

    /**
     * @brief 获取单例实例
     */
    static RelayApp& GetInstance() {
        static RelayApp instance;
        return instance;
    }

    // 删除拷贝构造函数和赋值运算符
    RelayApp(const RelayApp&) = delete;
    RelayApp& operator=(const RelayApp&) = delete;

    bool start();
    
    /**
     * @brief 处理MQTT消息（8字节协议格式）
     * @param topic MQTT主题
     * @param payload 8字节协议数据
     * @param length 数据长度
     */
    void ProcessProtocolMessage(const char* topic, const uint8_t* payload, size_t length);

private:
    RelayApp();
    ~RelayApp() = default;

    std::shared_ptr<TaskExecutor> task_executor_;
    char get_topic[40]="";
    char send_topic[40]="";
    std::array<PCF8574*, 3> pcf8574_array_;//[1]L1(0x20),[0]L2(0x21),[2]L3(0x22)
    uint8_t relay_state_[3] = {0}; // 2个字节存储14路继电器状态，对应relay_state[0]和relay_state[1]
    uint8_t data_back_[8] = {0x22, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; // 回复数据包
    
    // Settings实例用于持久化保存继电器状态
    std::unique_ptr<Settings> settings_;

    //必须是静态，C++的类中的函数自带this，只有静态不带，符合c风格
    static void CallBack(const char* topic, const char* payload, size_t length, void* user_data);
    
    /**
     * @brief 计算校验和
     * @param data 数据指针
     * @param len 数据长度
     * @return 校验和
     */
    uint8_t GetChecksum(const uint8_t* data, uint8_t len);
    
    /**
     * @brief 返回继电器状态
     */
    void ReturnRelayState();
    
    /**
     * @brief 打开指定继电器
     * @param relay_num 继电器编号 (1-14)
     */
    void RelayOpen(uint8_t relay_num);
    
    /**
     * @brief 关闭指定继电器
     * @param relay_num 继电器编号 (1-14)
     */
    void RelayClose(uint8_t relay_num);
    
    /**
     * @brief 打开所有继电器
     */
    void AllOpen();
    
    /**
     * @brief 关闭所有继电器
     */
    void AllClose();
    
    /**
     * @brief 延时操作（打开->延时->关闭）
     * @param relay_num 继电器编号 (1-14)
     * @param delay_ms 延时时间(毫秒)
     */
    void RelayOpenDelay(uint8_t relay_num, uint32_t delay_ms);
    
    /**
     * @brief 延时操作（关闭->延时->打开）
     * @param relay_num 继电器编号 (1-14)  
     * @param delay_ms 延时时间(毫秒)
     */
    void RelayCloseDelay(uint8_t relay_num, uint32_t delay_ms);
    
    /**
     * @brief 更新PCF8574输出状态 (双引脚继电器控制)
     * @param relay_num 继电器编号 (1-14)
     * @param state 状态 (0=关闭, 1=打开)
     */
    void UpdatePCF8574Output(uint8_t relay_num, uint8_t state);
    
    /**
     * @brief 发布MQTT消息
     * @param data 数据指针
     * @param length 数据长度
     */
    void PublishMqttMessage(const uint8_t* data, size_t length);
    
    /**
     * @brief 保存继电器状态到NVS
     */
    void SaveRelayStates();
    
    /**
     * @brief 从NVS恢复继电器状态
     */
    void RestoreRelayStates();
    
    /**
     * @brief 恢复单个继电器的物理状态（仅设置硬件，不保存NVS）
     * @param relay_num 继电器编号 (1-14)
     * @param state 状态 (0=关闭, 1=打开)
     */
    void RestoreRelayPhysicalState(uint8_t relay_num, uint8_t state);

};

#endif // RELAY_APP_H 